package com.sen.rbac.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sen.common.common.enums.CommonEnum;
import com.sen.common.common.exception.RecordNotFoundException;
import com.sen.common.common.response.PageVo;
import com.sen.common.common.util.SnowflakeIdWorker;
import com.sen.common.user.config.UserContextHolder;
import com.sen.rbac.constant.RbacConstant;
import com.sen.rbac.dto.SysAccountDto;
import com.sen.rbac.dto.SysTenantDTO;
import com.sen.rbac.dto.SysTenantResourceDTO;
import com.sen.rbac.exception.RbacException;
import com.sen.rbac.mapper.SysRoleAccountDao;
import com.sen.rbac.mapper.SysRoleDao;
import com.sen.rbac.mapper.SysTenantAccountDao;
import com.sen.rbac.mapper.SysTenantDao;
import com.sen.rbac.model.SysRole;
import com.sen.rbac.model.SysRoleAccount;
import com.sen.rbac.model.SysTenant;
import com.sen.rbac.model.SysTenantAccount;
import com.sen.rbac.service.AccountService;
import com.sen.rbac.service.RoleService;
import com.sen.rbac.service.SysTenantService;
import com.sen.rbac.vo.SysTenantVO;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.sen.common.common.response.ResultMsgEnum.RECORD_NOT_EXIST;
import static com.sen.rbac.enums.RbacMsgEnum.ACCOUNT_DUPLICATE_ERROR;
import static com.sen.rbac.enums.RbacMsgEnum.tenant_not_exist;

/**
 * @author esjiang
 */
@Service
public class SysTenantServiceImpl extends ServiceImpl<SysTenantDao, SysTenant> implements SysTenantService {

    @Resource
    AccountService accountService ;

    @Resource
    RoleService roleService ;

    @Resource
    SysRoleDao roleDao ;

    @Resource
    SysRoleAccountDao sysRoleAccountDao ;

    @Resource
    ModelMapper modelMapper ;

    @Resource
    SysTenantDao sysTenantDao ;

    @Resource
    SysTenantAccountDao sysTenantAccountDao;

    @Override
    public PageVo<SysTenantVO> list(SysTenantDTO sysTenantDTO) {
        IPage<SysTenantVO> list = sysTenantDao.list(new Page<>(sysTenantDTO.getPage(), sysTenantDTO.getPageSize()), sysTenantDTO.getArea(), sysTenantDTO.getTenantName());
        return PageVo.<SysTenantVO>builder().list(list.getRecords()).total(list.getTotal()).build();
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void saveOrUpdate(SysTenantDTO sysTenantDTO) {
        if (ObjectUtil.isNotNull(sysTenantDTO.getId())){
            SysTenant sysTenant = getById(sysTenantDTO.getId());
            sysTenant.setArea(sysTenantDTO.getArea());
            sysTenant.setTenantName(sysTenantDTO.getTenantName());
            saveOrUpdate(sysTenant) ;
            return;
        }
        SysAccountDto sysAccountDto = new SysAccountDto();
        sysAccountDto.setUserName(sysTenantDTO.getAdministrator());
        sysAccountDto.setPassword(sysTenantDTO.getPassword());
        sysAccountDto.setUserType(RbacConstant.user_type_2);
        sysAccountDto.setEntityCode(UserContextHolder.getPeople().getEntityCode());
        if (StrUtil.isBlank(sysTenantDTO.getTenantCode())){
            boolean flag = accountService.checkUniqueAccount(sysTenantDTO.getAdministrator());
            if (!flag){
                throw new RbacException(ACCOUNT_DUPLICATE_ERROR) ;
            }
            sysTenantDTO.setTenantCode(SnowflakeIdWorker.generateStrId());
            accountService.addAccount(sysAccountDto) ;
        }
        /** 写入区划账户关联表 */
        SysTenantAccount sysTenantAccount = new SysTenantAccount();
        sysTenantAccount.setTenantCode(sysTenantDTO.getTenantCode());
        sysTenantAccount.setUserName(sysAccountDto.getUserName());
        sysTenantAccountDao.insert(sysTenantAccount) ;
        /** 写入区划表 */
        saveOrUpdate(modelMapper.map(sysTenantDTO,SysTenant.class));
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void del(String id) {
        SysTenant sysTenant = getById(id);
        if (ObjectUtil.isNull(sysTenant)){
            throw new RecordNotFoundException(RECORD_NOT_EXIST) ;
        }
        sysTenant.setEnable(CommonEnum.ENABLE_NO.getCode());
        saveOrUpdate(sysTenant) ;
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void relatedResource(SysTenantResourceDTO sysTenantResourceDTO) {
        /** 创建角色或删除角色 */
        SysTenant sysTenant = getOne(Wrappers.<SysTenant>lambdaQuery().eq(SysTenant::getTenantCode, sysTenantResourceDTO.getTenantCode()));
        if (ObjectUtil.isNull(sysTenant)){
            throw new RecordNotFoundException(tenant_not_exist) ;
        }
        /** 判断是否已经存在角色，运营专员只有一个角色 ，一个运营专员只能管理一个区划*/
        String roleCode  ;
        SysRoleAccount sysRoleAccount = sysRoleAccountDao.selectOne(Wrappers.<SysRoleAccount>lambdaQuery().eq(SysRoleAccount::getUserName,sysTenant.getAdministrator()));
        if (ObjectUtil.isNull(sysRoleAccount)){
            SysRole sysRole = SysRole.builder().code(SnowflakeIdWorker.generateStrId()).
                    tenantCode(sysTenantResourceDTO.getTenantCode())
                    .name(generateRoleName(sysTenant))
                    .entityCode(UserContextHolder.getPeople().getEntityCode())
                    .groupCode(sysTenantResourceDTO.getRoleGroupCode())
                    .build();
            roleDao.insert(sysRole) ;
            /** 把角色关联到区划管理员 */
            sysRoleAccountDao.insert(SysRoleAccount.builder().roleCode(sysRole.getCode()).userName(sysTenant.getAdministrator()).build()) ;
            roleCode = sysRole.getCode() ;
        }else {
            roleCode = sysRoleAccount.getRoleCode() ;
        }
        /** 关联资源  */
        roleService.relatedResource(roleCode, sysTenantResourceDTO.getResourceCodes());
    }

    /**
     * 生成角色名称
     * @param sysTenant
     * @return
     */
    private String generateRoleName(SysTenant sysTenant ){
        return sysTenant.getTenantName() + RbacConstant.tenantRoleName_suffix;
    }

    @Override
    public List<SysTenantVO> listTenants(){
        List<SysTenant> tenants=sysTenantDao.selectList(Wrappers.<SysTenant>lambdaQuery().eq(SysTenant::getEnable,CommonEnum.ENABLE_YES.getCode()));
        List<SysTenantVO> vos= new ArrayList<>();
        if (CollUtil.isNotEmpty(tenants)){
            return tenants.stream().map(record -> modelMapper.map(record, SysTenantVO.class)).collect(Collectors.toList());
        }
        return vos;
    }


}
